package com.yboot.starter.tenant.core.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yboot.starter.tenant.core.api.TenantIdApi;
import com.yboot.starter.tenant.core.context.TenantContextHolder;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class TenantContextFilter extends OncePerRequestFilter {
    // @TODO 可以改成自己安全拦截器AbstractOncePerRequestFilter
    private TenantIdApi tenantIdApi;
    private ObjectMapper objectMapper;

    private final List<RequestMatcher> ignoredAntMatchers = new ArrayList();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            String tenantId = TenantContextHolder.getTenantId();
            if (StringUtils.hasLength(tenantId)) {
                filterChain.doFilter(request, response);
                return;
            }
            tenantId = this.tenantIdApi.getTenantId();
            if (!StringUtils.hasLength(tenantId)) {
//                FanlinksRuntimeException fanlinksRuntimeException = new FanlinksRuntimeException(ErrorCodeEnum.TENANT_ID_IS_EMPTY);
//                Response<Object> r = Response.error(String.valueOf(HttpStatus.UNAUTHORIZED.value()), fanlinksRuntimeException.getMessage());
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                response.setContentType("application/json");
                this.objectMapper.writeValue(response.getWriter(), "tenantId不存在或用户未登录");
                return;
            }
            TenantContextHolder.setTenantId(tenantId);
            filterChain.doFilter(request, response);
        } finally {
            TenantContextHolder.clearTenantId();
        }
    }

    public TenantContextFilter(TenantIdApi tenantIdApi, ObjectMapper objectMapper) {
        this.tenantIdApi = tenantIdApi;
        this.objectMapper = objectMapper;
    }

    public void ignoredAntPatterns(String... ignoredAntPatterns) {
        this.ignoredAntMatchers.addAll(antMatchers(null, ignoredAntPatterns));
    }

    public static List<RequestMatcher> antMatchers(HttpMethod httpMethod, String... antPatterns) {
        if (antPatterns == null) {
            return Collections.emptyList();
        } else {
            String method = httpMethod != null ? httpMethod.toString() : null;
            List<RequestMatcher> matchers = new ArrayList();
            for(int i = 0; i < antPatterns.length; ++i) {
                String pattern = antPatterns[i];
                matchers.add(new AntPathRequestMatcher(pattern, method));
            }

            return matchers;
        }
    }

    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        Iterator var2 = this.ignoredAntMatchers.iterator();

        RequestMatcher antMatcher;
        do {
            if (!var2.hasNext()) {
                return super.shouldNotFilter(request);
            }

            antMatcher = (RequestMatcher)var2.next();
        } while(!antMatcher.matches(request));

        return true;
    }
}